﻿using System;
using System.Collections.Generic;

namespace Cookie.Library.Pool
{
    /// <summary>
    /// Based on example from:
    /// http://msdn2.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.socketasynceventargs.aspx
    /// Represents a collection of reusable SocketAsyncEventArgs objects. 
    /// 原例用于SocketAsyncEventArgs，扩展后用于同类的事件参数 
    /// </summary>
    internal sealed class AsyncEventArgsPool<T> : IEnumerable<T> where T:EventArgs
    {
        /// <summary>
        /// SocketAsyncEventArgs栈
        /// </summary>
        Stack<T> pool;

        /// <summary>
        /// 初始化AsyncEventArgsPool池
        /// </summary>
        /// <param name="capacity">最大可能使用的SocketAsyncEventArgs对象.</param>
        internal AsyncEventArgsPool(Int32 capacity)
        {
            this.pool = new Stack<T>(capacity);
        }

        /// <summary>
        /// 返回AsyncEventArgsPool池中的 数量
        /// </summary>
        internal int Count
        {
            get { return this.pool.Count; }
        }

        internal void Clear()
        {
            lock (this.pool)
            {
                this.pool.Clear();
            }
        }

        /// <summary>
        /// 弹出一个AsyncEventArgsPool
        /// </summary>
        /// <returns>AsyncEventArgsPool removed from the pool.</returns>
        internal T Pop()
        {
            lock (this.pool)
            {
                return this.pool.Pop();
            }
        }

        /// <summary>
        /// 添加一个 AsyncEventArgsPool
        /// </summary>
        /// <param name="item">AsyncEventArgsPool instance to add to the pool.</param>
        internal void Push(T item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null");
            }
            lock (this.pool)
            {
                this.pool.Push(item);
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return pool.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return pool.GetEnumerator();
        }
    }
}
